/****************************************************************
 ** Product  :   HP Subscriber Network Application Policy
 ** Module   :   gr-manager
 ** Date: Apr 10, 2015               
 ** Author: Hua Zhen
 ** (C) Copyright 2015, Hewlett-Packard Company, All Rights Reserved.
 ** This software is the proprietary information of HP, Inc.  
 ** Use is subject to license terms.
 *****************************************************************
 ** Description:   
 **
 **    Promote the DB cluster from Replica mode to Master mode.
 **    
 ****************************************************************/
package com.hp.snap.gr.action.impl;

import com.hp.snap.gr.exception.ActionException;
import com.hp.snap.gr.model.Database;
import com.hp.snap.gr.model.jaxb.ActionType;
import com.hp.snap.gr.model.jaxb.GeneralActionType;
import com.hp.snap.gr.model.jaxb.ParameterType;
import com.hp.snap.gr.utils.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;

/**
 * Get the DB status by call "/mgmt/databases" interface.
 * if the DB instance is "online" and "replica", the DB instance will be promote to "master" status by invoke "@Promote" store procedure.
 * if the DB instance is "offline", the DB instance will be recovered to "master" status call the "/mgmt/databases/<database_id>/recover" restful interface.
 * 
 * There is a parameter need to be configured in the action: DB_INSTANCE_NAME
 * DB_INSTANCE_NAME: The VoltDB DB instance name, such as: spr_db, session_db, lb_db;
 * 
 * <P>
 * Version: 3.3 <br>
 * Author: Hua Zhen
 * Date: Apr 10, 2015
 * 
 * </P>
 * 
 **/
public class PromoteVoltDBToMasterActionHandler extends AbstractActionHandler {
    private static Logger logger = LoggerFactory.getLogger(PromoteVoltDBToMasterActionHandler.class);

    @Override
    public void execute(ActionType action,
                        Map<String, Object> actionPlanInputs,
                        Map<String, Object> actionPlanOutputs) throws ActionException {
        GeneralActionType actionType = (GeneralActionType) action;
        List<ParameterType> parameterTypes = actionType.getParameter();
        Map<String, String> parameterMap = Utils.contructParamMap(parameterTypes);

        /**
         * get the db instance name, which should be configured in: /SNAP/GR/<DEPLOY_NAME>/VOLTDB/<DB_INSTANCE_NAME>, e.g.
         * /SNAP/GR/Site_A1/VOLTDB/session_db]
         */
        String dbInstName = parameterMap.get("DB_INSTANCE_NAME");
        if (StringUtils.isEmpty(dbInstName)) {
            throw new ActionException("The parameter [DB_INSTANCE_NAME] should be configured!");
        }

        // find out the target database profile
        Database database = RESTfulUtils.getVoltDBDatabase(dbInstName);

        if (database == null) {
            throw new ActionException("The database instance is not exist: " + dbInstName);
        }

        String status = database.getStatus();
        boolean replica = database.isReplica();

        if (Constants.VDB_STATUS_ONLINE.equals(status) || Constants.VDB_STATUS_PAUSED.equals(status)) {
            if (!replica) {    // check current staring mode, if starting mode is master, return result immediately
                logger.info("The DB Instance [{}] already running in master mode!", dbInstName);
            } else {    // if current status is running, stop the server before promotion.
                database = RESTfulUtils.getVoltDBDatabase(dbInstName);
                if (database == null) {
                    throw new ActionException("After updating, the database instance is not exist: " + dbInstName);
                }
                VoltDBStoreProcedureController.promoteDatabase(database, GRMConfigManager.getSiteName());
            }
        } else if (Constants.VDB_STATUS_OFFLINE.equals(status)) {

            if (logger.isDebugEnabled()) {
                logger.debug("recovering the DB Instance, Name: {}, ID: {}", dbInstName, database.getId());
            }
            VoltDBController.recoverDatabase(database);

            logger.info("promote the DB Instance successful to master mode, Name: {}, ID: {}", dbInstName, database.getId());

        } else {
            logger.warn("The database is in status [{}], and do not process!", status);
        }
    }
}
